<!DOCTYPE html>
<html>
<head>
<title>Physics Diagram</title>
<style>
  body {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    margin: 0;
    background-color: #f0f0f0;
  }
  canvas {
    border: 1px solid #ccc;
    background-color: #fff;
  }
</style>
</head>
<body>
<canvas id="physicsCanvas" width="600" height="400"></canvas>
<script>
  const canvas = document.getElementById('physicsCanvas');
  const ctx = canvas.getContext('2d');

  /**
   * Draws a line from (fromx, fromy) to (tox, toy) with a filled arrowhead at the end.
   * @param {CanvasRenderingContext2D} ctx - The canvas rendering context.
   * @param {number} fromx - The x-coordinate of the starting point.
   * @param {number} fromy - The y-coordinate of the starting point.
   * @param {number} tox - The x-coordinate of the ending point.
   * @param {number} toy - The y-coordinate of the ending point.
   * @param {number} [headlen=10] - The length of the arrowhead sides.
   */
  function drawArrow(ctx, fromx, fromy, tox, toy, headlen = 10) {
    const dx = tox - fromx;
    const dy = toy - fromy;
    const angle = Math.atan2(dy, dx);

    // Draw the line part
    ctx.beginPath();
    ctx.moveTo(fromx, fromy);
    ctx.lineTo(tox, toy);
    ctx.stroke();

    // Draw the filled arrowhead
    ctx.beginPath();
    ctx.moveTo(tox, toy);
    ctx.lineTo(tox - headlen * Math.cos(angle - Math.PI / 6), toy - headlen * Math.sin(angle - Math.PI / 6));
    ctx.lineTo(tox - headlen * Math.cos(angle + Math.PI / 6), toy - headlen * Math.sin(angle + Math.PI / 6));
    ctx.closePath();
    ctx.fill();
  }

  // --- Main Drawing ---

  // Style settings
  ctx.strokeStyle = 'black';
  ctx.fillStyle = 'black';
  
  // Coordinate and dimension settings
  const yTopE = 80;
  const yBottomE = 320;
  const yLine = 200;
  const yDim = 270;
  
  const xStart = 50;
  const xEnd = 550;
  
  const xA = 180;
  const xB = 420;
  const xCenter = (xA + xB) / 2;

  // 1. Draw Electric Field (E)
  ctx.lineWidth = 2;
  ctx.font = 'italic 24px Times New Roman';
  drawArrow(ctx, xStart, yTopE, xEnd, yTopE);
  ctx.fillText('E', xEnd + 10, yTopE + 8);
  
  drawArrow(ctx, xStart, yBottomE, xEnd, yBottomE);
  ctx.fillText('E', xEnd + 10, yBottomE + 8);

  // 2. Draw dashed line for particle path
  ctx.save();
  ctx.lineWidth = 1.5;
  ctx.setLineDash([8, 8]);
  ctx.beginPath();
  ctx.moveTo(xStart - 20, yLine);
  ctx.lineTo(xEnd + 20, yLine);
  ctx.stroke();
  ctx.restore();

  // 3. Draw Particles (A and B)
  const particleRadius = 5;
  ctx.beginPath();
  ctx.arc(xA, yLine, particleRadius, 0, 2 * Math.PI);
  ctx.fill();

  ctx.beginPath();
  ctx.arc(xB, yLine, particleRadius, 0, 2 * Math.PI);
  ctx.fill();

  // 4. Draw labels for particles
  ctx.textAlign = 'center';
  
  // Labels m, Q and m (italic)
  ctx.font = 'italic 22px Times New Roman';
  ctx.textBaseline = 'bottom';
  ctx.fillText('m, Q', xA, yLine - 15);
  ctx.fillText('m', xB, yLine - 15);
  
  // Labels A and B (upright)
  ctx.font = '22px Times New Roman';
  ctx.textBaseline = 'top';
  ctx.fillText('A', xA, yLine + 10);
  ctx.fillText('B', xB, yLine + 10);

  // 5. Draw distance dimension (l)
  ctx.lineWidth = 1.5;
  
  // Vertical ticks
  ctx.beginPath();
  ctx.moveTo(xA, yDim - 10);
  ctx.lineTo(xA, yDim + 10);
  ctx.stroke();
  
  ctx.beginPath();
  ctx.moveTo(xB, yDim - 10);
  ctx.lineTo(xB, yDim + 10);
  ctx.stroke();

  // Arrows and label 'l'
  ctx.font = 'italic 22px Times New Roman';
  ctx.textAlign = 'center';
  ctx.textBaseline = 'middle';
  const labelL = 'l';
  const lWidth = ctx.measureText(labelL).width;
  
  // Draw the label 'l' in the center
  ctx.fillText(labelL, xCenter, yDim);

  // Draw the two arrows pointing outwards from the label
  drawArrow(ctx, xCenter - lWidth / 2 - 4, yDim, xA, yDim, 8);
  drawArrow(ctx, xCenter + lWidth / 2 + 4, yDim, xB, yDim, 8);

  // 6. Draw Caption
  ctx.fillStyle = 'black';
  ctx.font = '20px SimSun';
  ctx.textAlign = 'center';
  ctx.textBaseline = 'bottom';
  ctx.fillText('电图 1.11.1', xCenter, canvas.height - 10);

</script>
</body>
</html>